
SELECTOR_KERNEL_CS      equ     8

; 导入函数
extern cstart
extern exception_handler
extern	spurious_irq

; 导入全局变量
extern gdt_ptr
extern idt_ptr
extern disp_pos

[SECTION .bss]
StackSpace      resb    2 * 1024
StackTop: ; 栈顶

[section .text] ; 代码段

global _start ; 导出入口点

global	divide_error
global	single_step_exception
global	nmi
global	breakpoint_exception
global	overflow
global	bounds_check
global	inval_opcode
global	copr_not_available
global	double_fault
global	copr_seg_overrun
global	inval_tss
global	segment_not_present
global	stack_exception
global	general_protection
global	page_fault
global	copr_error

global  hwint00
global  hwint01
global  hwint02
global  hwint03
global  hwint04
global  hwint05
global  hwint06
global  hwint07
global  hwint08
global  hwint09
global  hwint10
global  hwint11
global  hwint12
global  hwint13
global  hwint14
global  hwint15

_start:
    ; 把 esp 从 LOADER 挪到 KERNEL
    mov     esp, StackTop   ; 堆栈在 bss 段中

    mov     dword [disp_pos], 0

    sgdt    [gdt_ptr]       ; cstart() 中将会用到 gdt_ptr
    call    cstart          ; 在此函数中改变了 gdt_ptr，让它指向新的 GDT
    lgdt    [gdt_ptr]       ; 使用新的 GDT

    lidt    [idt_ptr]       ; 注册 LDT

    jmp     SELECTOR_KERNEL_CS:csinit
csinit:
    ;ud2        ; 这个没问题
    ;jmp 0x40:0 ; 这个书上说可以打印错误码，可我这里并没有，而且拿源码测试也是一样。

    sti
    hlt

; 中断和异常 -- 硬件中断
; ---------------------------------
%macro  hwint_master    1
        push    %1
        call    spurious_irq
        add     esp, 4
        hlt
%endmacro
; ---------------------------------

ALIGN   16
hwint00:                ; Interrupt routine for irq 0 (the clock).
        hwint_master    0

ALIGN   16
hwint01:                ; Interrupt routine for irq 1 (keyboard)
        hwint_master    1

ALIGN   16
hwint02:                ; Interrupt routine for irq 2 (cascade!)
        hwint_master    2

ALIGN   16
hwint03:                ; Interrupt routine for irq 3 (second serial)
        hwint_master    3

ALIGN   16
hwint04:                ; Interrupt routine for irq 4 (first serial)
        hwint_master    4

ALIGN   16
hwint05:                ; Interrupt routine for irq 5 (XT winchester)
        hwint_master    5

ALIGN   16
hwint06:                ; Interrupt routine for irq 6 (floppy)
        hwint_master    6

ALIGN   16
hwint07:                ; Interrupt routine for irq 7 (printer)
        hwint_master    7

; ---------------------------------
%macro  hwint_slave     1
        push    %1
        call    spurious_irq
        add     esp, 4
        hlt
%endmacro
; ---------------------------------

ALIGN   16
hwint08:                ; Interrupt routine for irq 8 (realtime clock).
        hwint_slave     8

ALIGN   16
hwint09:                ; Interrupt routine for irq 9 (irq 2 redirected)
        hwint_slave     9

ALIGN   16
hwint10:                ; Interrupt routine for irq 10
        hwint_slave     10

ALIGN   16
hwint11:                ; Interrupt routine for irq 11
        hwint_slave     11

ALIGN   16
hwint12:                ; Interrupt routine for irq 12
        hwint_slave     12

ALIGN   16
hwint13:                ; Interrupt routine for irq 13 (FPU exception)
        hwint_slave     13

ALIGN   16
hwint14:                ; Interrupt routine for irq 14 (AT winchester)
        hwint_slave     14

ALIGN   16
hwint15:                ; Interrupt routine for irq 15
        hwint_slave     15

; 中断的异常处理
divide_error:
    push    0xFFFFFFFF  ; 没有错误码
    push    0           ; 中断码
    jmp     exception
single_step_exception:
    push    0xFFFFFFFF  ; 没有错误码
    push    1           ; 中断码
    jmp     exception
nmi:
    push    0xFFFFFFFF  ; 没有错误码
    push    2           ; 中断码
    jmp     exception
breakpoint_exception:
    push    0xFFFFFFFF  ; 没有错误码
    push    3           ; 中断码
    jmp     exception
overflow:
    push    0xFFFFFFFF  ; 没有错误码
    push    4           ; 中断码
    jmp     exception
bounds_check:
    push    0xFFFFFFFF  ; 没有错误码
    push    5           ; 中断码
    jmp     exception
inval_opcode:
    push    0xFFFFFFFF  ; 没有错误码
    push    6           ; 中断码
    jmp     exception
copr_not_available:
    push    0xFFFFFFFF  ; 没有错误码
    push    7           ; 中断码
    jmp     exception
double_fault:
    push    0xFFFFFFFF  ; 没有错误码
    push    8           ; 中断码
    jmp     exception
copr_seg_overrun:
    push    0xFFFFFFFF  ; 没有错误码
    push    9           ; 中断码
    jmp     exception
inval_tss:
    push    0xFFFFFFFF  ; 没有错误码
    push    10          ; 中断码 = A
    jmp     exception
segment_not_present:
    push    0xFFFFFFFF  ; 没有错误码
    push    11          ; 中断码 = B
    jmp     exception
stack_exception:
    push    0xFFFFFFFF  ; 没有错误码
    push    12          ; 中断码 = C
    jmp     exception
general_protection:
    push    0xFFFFFFFF  ; 没有错误码
    push    13          ; 中断码 = D
    jmp     exception
page_fault:
    push    0xFFFFFFFF  ; 没有错误码
    push    14          ; 中断码 = E
    jmp     exception
copr_error:
    push    0xFFFFFFFF  ; 没有错误码
    push    16          ; 中断码 = 10h
    jmp     exception

exception:
    call    exception_handler
    add     esp, 4 * 2  ; 让栈顶指向 EIP，堆栈中从顶向下依次是：EIP、CS、EFLAGS
    hlt


